#include "CalendarAdvance.h"

/********************************************/
/*			CalendarAdvance					*/
/********************************************/

CalendarAdvance::CalendarAdvance(int nof_days) : Calendar(nof_days){
	createDays(nof_days);
}

CalendarAdvance::~CalendarAdvance(){
}

CalendarError CalendarAdvance::createMeeting(const char *subject, float startTime, float endTime, int day, const char *names,/*out*/const Meeting *&meeting){
	Day *dayp;
	CalendarError res = getDay(day, dayp);
	if (res != CALENDAR_ERROR_NONE) return res;

	meeting = (Meeting *) new MeetingAdvance(startTime, endTime, subject,names, *dayp, *this); 
	if (meeting == NULL) return CALENDAR_ERROR_MEMORY;

	return CALENDAR_ERROR_NONE;

}

CalendarError CalendarAdvance::moveMeeting(const Meeting &meeting, float startTime, float endTime, int day, /*out*/const Meeting *&newMeeting) {
	Day *oldDay;
	
	CalendarError res =  meeting.getDay(oldDay);
	if (res != CALENDAR_ERROR_NONE) return res;
	
	const char *subject;
	res =  meeting.getSubject(subject);
	if (res != CALENDAR_ERROR_NONE) return res;
	

	const char *names;
	if (meeting.whoAmI() == MEETING_ADVANCE) {
		CalendarError res =  ((MeetingAdvance &) meeting).getNames(names);
		if (res != CALENDAR_ERROR_NONE) return res;
		res = createMeeting(subject, startTime, endTime, day, names, newMeeting);
		if (res != CALENDAR_ERROR_NONE) return res;
	} else {
		res = this->Calendar::createMeeting(subject, startTime, endTime, day, newMeeting);
		if (res != CALENDAR_ERROR_NONE) return res;
	}
	
	res = oldDay->deleteMeeting(meeting);
	if (res != CALENDAR_ERROR_NONE) return res;
	delete &meeting;
	
	res = addMeeting(*newMeeting);
	if (res != CALENDAR_ERROR_NONE) return res;

	return CALENDAR_ERROR_NONE;
}

int CalendarAdvance::whoAmI() const {
	return CALENDAR_ADVANCE;
}

/********************************************/
/*			MeetingAdvance					*/
/********************************************/


MeetingAdvance::MeetingAdvance(float startTime, float endTime, const char* subject, const char *names, Day &day, Calendar &calendar) 
	: Meeting(startTime, endTime, subject, day, calendar)
{
	setNames(names);
};

MeetingAdvance::~MeetingAdvance() {
};

CalendarError MeetingAdvance::getNames(const char *&names) const {
	names = this->names;
	return CALENDAR_ERROR_NONE;
}

CalendarError MeetingAdvance::setNames(const char *&names) {
	this->names = names;
	return CALENDAR_ERROR_NONE;
}

CalendarError MeetingAdvance::printAll() const{
	float startTime;
	CalendarError res = getStartTime(startTime);
	if (res != CALENDAR_ERROR_NONE) return res;
	int startTimeHour = (int) startTime;
	int startTimeMinutes = 60*(startTime - (int) startTime);

	float endTime;
	res = getEndTime(endTime);
	if (res != CALENDAR_ERROR_NONE) return res;
	int endTimeHour = (int) endTime;
	int endTimeMinutes = 60*(endTime - (int) endTime);

	Day *thisDay;
	res = this->getDay(thisDay);
	if (res != CALENDAR_ERROR_NONE) return res;

	int dayNumber;
	res = thisDay->getDayNumber(dayNumber);
	if (res != CALENDAR_ERROR_NONE) return res;

	const char *subject;
	res = this->getSubject(subject);
	if (res != CALENDAR_ERROR_NONE) return res;

	const char *names;
	res = this->getNames(names);
	if (res != CALENDAR_ERROR_NONE) return res;


	cout << "+------------------------------+-----+----------+--------+------------------"<< endl;
	cout << "|            Subject           | Day | Start at | End at |    Names         "<< endl;
	cout << "+------------------------------+-----+----------+--------+------------------"<< endl;
	printf( "| %-29s| %3d |   %02d:%02d  |  %02d:%02d |%-10s\n", subject, dayNumber, startTimeHour, startTimeMinutes, endTimeHour, endTimeMinutes, names);
	cout << "+------------------------------+-----+----------+--------+------------------"<< endl;
	return CALENDAR_ERROR_NONE;
}

int MeetingAdvance::whoAmI() const {
	return MEETING_ADVANCE;
}

CalendarError MeetingAdvance::isOverlap(const Meeting &meeting, /*out*/ bool &status)  const{
	status = false;
	CalendarError res =  this->Meeting::isOverlap(meeting, status);
	if (res != CALENDAR_ERROR_NONE) return res;

	if (!status) return CALENDAR_ERROR_NONE;
	status = false; /*next stage checking*/

	if (meeting.whoAmI() == MEETING) return CALENDAR_ERROR_NONE;

	const char* namesThis;
	char name[100];

	res = getNames(namesThis);
	if (res != CALENDAR_ERROR_NONE) return res;


	int start = 0;
	int nameLength = strlen(namesThis);
	for (int i=0; i<nameLength ; i++) {
		if (namesThis[i] == ' ' || namesThis[i] == '\n') {
			memcpy(name, &(namesThis[start]), (i-start)*sizeof(char));
			name[i-start] = '\0';
			if (((MeetingAdvance &)meeting).isIncludeName(name)) {
				status = true;
				return CALENDAR_ERROR_NONE;
			}
			start = i+1;
		} else if (i == nameLength - 1) {
			memcpy(name, &(namesThis[start]), (i-start + 1)*sizeof(char));
			name[i-start + 1] = '\0';
			if (((MeetingAdvance &)meeting).isIncludeName(name)) {
				status = true;
				return CALENDAR_ERROR_NONE;
			} 

		}
	}
	return CALENDAR_ERROR_NONE;
}

bool MeetingAdvance::isIncludeName(const char *name) const {
	const char* namesThis;
	char nameCur[100];

	CalendarError res = getNames(namesThis);
	if (res != CALENDAR_ERROR_NONE) return res;

	int start = 0;
	int nameLength = strlen(namesThis); 
	for (int i=0; i<nameLength; i++) {
		if (namesThis[i] == ' ' || namesThis[i] == '\n') {
			memcpy(nameCur, &(namesThis[start]), (i-start)*sizeof(char));
			nameCur[i-start] = '\0';
			if (strcmp(name, nameCur) == 0) {
				return true;
			}
			start = i+1;
		} else if (i == nameLength - 1) {
			memcpy(nameCur, &(namesThis[start]), (i-start + 1)*sizeof(char));
			nameCur[i-start + 1] = '\0';
			if (strcmp(name, nameCur) == 0) {
				return true;
			} 

		}
	}

	return false;
}